from collections.abc import Generator
from typing import Annotated

from fastapi import Request, Depends
from fastapi.security import OAuth2PasswordBearer

from sqlmodel import Session
from pydantic import ValidationError
import jwt
from jwt.exceptions import InvalidTokenError
from app.core import security
from app.core.config import settings
from app.core.database import engine
from app.exception.base import AppException, HttpResp
from app.models.system_admin import SystemAdmin


def get_db() -> Generator[Session, None, None]:
    with Session(engine) as session:
        yield session


SessionDep = Annotated[Session, Depends(get_db)]

# JWT 依赖
OAuth2 = OAuth2PasswordBearer(tokenUrl="token")
TokenDep = Annotated[str, Depends(OAuth2)]

# 前台用户 Token 校验
async def verify_token(request: Request, session: SessionDep, token: TokenDep):
    """校验Token"""
    # Token是否为空
    if not token:
        raise AppException(HttpResp.NO_AUTH)
    try:
        # token解密
        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[security.ALGORITHM])
        # token_data = TokenPayload(**payload)
        if payload:
            # 用户ID
            user_id = payload.get("user_id", None)
            # 用户类型
            username = payload.get("username", None)
            # 无效用户信息
            if user_id is None or username is None:
                raise AppException(HttpResp.NO_AUTH)
        else:
            # Token 不合法
            raise AppException(HttpResp.NO_AUTH)

    except (InvalidTokenError, ValidationError):
        raise AppException(HttpResp.NO_AUTH)

    # ---------------------------------------验证权限-------------------------------------------------------------------
    # 查询用户是否真实有效、或者已经被禁用
    admin_user = session.get(SystemAdmin, user_id)
    # or admin_user.status != 1
    if admin_user is None or admin_user.is_disable == 1:
        raise AppException(HttpResp.LOGIN_DISABLE_ERROR)
    # 单次请求信息保存
    print('jwt token', admin_user)
    request.state.admin_id = admin_user.id
    # request.state.tenant_id = admin_user.tenant_id
    request.state.is_super = admin_user.is_super
    request.state.username = admin_user.username

